计蒜客 贝壳找房与送水员 发表于 2018-06-18 1234567891011121314好题发现了两个v的做法但是没发现一个v的按照之前的思路死活做不出来,这时候要跳出之前的思维模式(重点!重点!重点!)不再是按照对位的边形成的树上找了而是考虑有没有环题解:1个v:现在题意变成了要求多组单向可达关系加最少有向边的问题。考虑每个弱联通子图,如果是个dag的话最少需要v-1个魔法(构造方法:用链将拓扑序串起来),否则的话至少需要v个魔法(一个大环)。然后加起来就好了。发现不会找弱连通子图哇哇哇dfs3+dfs2,再开两个vis数组丑的不行的代码 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153#include<bits/stdc++.h>#define mp make_pair#define pb push_backusing namespace std;typedef long long LL;typedef pair<int,int> PII;inline LL read(){ LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;}const int N=100008,shiwan=100000;int n;char s[20];int cnt;int a[N],b[N];bool vis[N],ins[N];vector<int> v;int nume,head[N];int nume_2,head_2[N];struct edge{ int to,nxt;}e[N<<1],e_2[N<<1];inline void add_edge(int x,int y){ e[++nume]=(edge){y,head[x]};head[x]=nume;}inline void add_edge_2(int x,int y){ e_2[++nume_2]=(edge){y,head_2[x]};head_2[x]=nume_2;}int ans;inline void dfs(int x){ vis[x]=0; for(int i=head[x];i;i=e[i].nxt){ if(vis[e[i].to]){ dfs(e[i].to); } }}bool flag;inline void dfs2(int x){ vis[x]=0; ins[x]=1; for(int i=head[x];i;i=e[i].nxt){ if(vis[e[i].to]){ dfs2(e[i].to); } else if(ins[e[i].to]){ flag=1; } } ins[x]=0;}bool vis2[N];inline void dfs3(int x){ if(vis[x]){ dfs2(x); } vis2[x]=1; for(int i=head_2[x];i;i=e_2[i].nxt){ if(!vis2[e_2[i].to]){ dfs3(e_2[i].to); } }}inline void solve(){ if(cnt==0){ for(int i=1;i<=n;++i){ if(a[i]!=b[i]){ puts("-1"); return; } } puts("0"); return; } if(cnt==1){ for(int i=1;i<=n;++i){ if(a[i]!=b[i]){ add_edge(a[i],b[i]); add_edge_2(a[i],b[i]); add_edge_2(b[i],a[i]); if(!vis[a[i]]){ v.pb(a[i]); vis[a[i]]=1; } if(!vis[b[i]]){ v.pb(b[i]); vis[b[i]]=1; } } } ans=v.size(); for(int i=0;i<v.size();++i){ if(vis[v[i]]){ flag=0; dfs3(v[i]); if(!flag) --ans; } } printf("%d",ans); return; } if(cnt==2){ for(int i=1;i<=n;++i){ if(a[i]!=b[i]){ add_edge(a[i],b[i]); add_edge(b[i],a[i]); if(!vis[a[i]]){ v.pb(a[i]); vis[a[i]]=1; } if(!vis[b[i]]){ v.pb(b[i]); vis[b[i]]=1; } } } ans=v.size(); for(int i=0;i<v.size();++i){ if(vis[v[i]]){ dfs(v[i]); --ans; } } printf("%d",ans); return; }}int main(){ //freopen("D.in","r",stdin); n=read(); scanf("%s",s+1); if(s[1]=='V') ++cnt; for(int i=1;i<=n;++i){ a[i]=read(); } scanf("%s",s+1); if(s[1]=='V') ++cnt; for(int i=1;i<=n;++i){ b[i]=read(); } solve(); return 0;}